//
//  MEMORY_RTL.h
//  sad
//
//  Created by Christopher Kemsley on 2/6/12.
//  Copyright (c) 2012 iAppolopolis. All rights reserved.
//

#ifndef sad_MEMORY_RTL_h
#define sad_MEMORY_RTL_h

#include "SystemCDefinitions.hpp"
#include "Log.hpp"


#define	MEM_SIZE	65535



/*	IMPORTANT NOTES
 
 If you drop in a replacement for this class:
 
 (1) Simply replace this file
 (2) Change "char*" to "char const*" to conform [more fully] with good-coding principles
 (3) Change <int> to <unsigned> to conform with prior interface declarations
 */



class MEMORY_RTL: public sc_module
{
public:
	sc_in<sc_logic> Clk;
	sc_in<sc_logic> Ren, Wen;
	sc_in<unsigned> Addr;
	sc_in<unsigned> DataIn;
	sc_out<unsigned> DataOut;
	sc_out<sc_logic> Ack;
	
	unsigned memData[MEM_SIZE]; 
	
	SC_HAS_PROCESS(MEMORY_RTL);
	
	
	
	MEMORY_RTL(sc_module_name name, char const* memInitFilename) : sc_module(name) 
		{
		_init_ascii ( memInitFilename ) ;
		SC_METHOD(rtl);
		sensitive << Clk.pos();
		}
	
	
	
	void rtl ()
		{
		SCLogic	ackValue	=	kSCLogicFalse ;
		
		if ( Ren->read() == kSCLogicTrue )
			{
			Log::states("MEMORY_RTL") << "Got read request on clock signal" ;
			unsigned	address	=	Addr->read() ;
			if ( address < MEM_SIZE )
				{
				Log::states("MEMORY_RTL") << "	--> Address within memory: " << address ;
				Log::states("MEMORY_RTL") << "	--> Reading: " << memData[address] ;
				ackValue = kSCLogicTrue ;
				DataOut -> write ( memData[address] ) ;
				}
			}
		else if ( Wen->read() == kSCLogicTrue )
			{
			Log::states("MEMORY_RTL") << "Got write request on clock signal" ;
			unsigned	address	=	Addr->read() ;
			if ( address < MEM_SIZE )
				{
				Log::states("MEMORY_RTL") << "	--> Address within memory: " << address ;
				ackValue = kSCLogicTrue ;
				memData[address] = DataOut -> read () ;
				Log::states("MEMORY_RTL") << "	--> Writing: " << memData[address] ;
				}
			}
		else
			{
			Log::states("MEMORY_RTL") << "No request pending" ;
			}
		
		Log::states("MEMORY_RTL") << "Writing acknowledge state to " << ( (ackValue==kSCLogicFalse) ? "false" : "true" ) ;
		Ack -> write ( ackValue ) ;
		}
	
	
	
	
	
	/** File reading **/
	
	void	_init_ascii ( char const* path )
		{
		FILE * file = fopen ( path , "r" ) ;
		
		if ( file != 0 )
			{
			unsigned remaining = MEM_SIZE ;
			unsigned * here = memData ;
			while ( !feof(file) && 0!=remaining-- )
				{
				fscanf ( file , "%*[^1234567890]" ) ;
				unsigned & value = *(here++) ;
				fscanf ( file , "%u" , &value ) ;
				}
			
			fclose ( file ) ;
			}
		else
			{
			Log::error("MEMORY_RTL") << "Failed to open memory initialization file" ;
			}
		}
};



#endif
